/*
 *  key_handler.c
 *  pire2pireV1
 *
 *  Created by jihed kamkoum on 04/05/10.
 *  Copyright 2010 ENSEIRB. All rights reserved.
 *
 */

#include "key_handler.h"

void checksum(const char * event,int * sock, int semid){
	if(*sock!=-1){
		sock_puts(*sock, event);
	}
	else {
		printf("No connection done !\n");
	}

}
void * f_thread_checksum(tchecksum * args){
	printf("debut thread %d\n",pthread_self());
	//retarder l'execution du thread pour que la priorite soit effective
	sleep(2);
	int semid= args->semid;
	char recived[100];
	memset((char *) &recived, 0, sizeof(recived));
	int ret = BUFSIZ + (args->nbblock * 100 );
	int i=args->nbblock;
	char cmd[ret];
	ret = -1;
	memset((char *) &cmd, 0, sizeof(cmd));
	strcpy(cmd,args->cmd);

	while (1) {
		if((ret=recv(args->sock, recived, sizeof(recived), 0))==-1)
			perror("receive");
		else if (ret !=0) {
			strcat(cmd,recived);
			memset((char *) &recived, 0, sizeof(recived));
			i--;
			if (i==0) {
				//plus rien a resevoir
				break;
			}
			sched_yield();
			sleep(1);
		}
	}
	printf("%s\n",cmd);
	struct sembuf op;
	op.sem_num = 0; //Test si le thread est dispo
	op.sem_op = 1; //V()
	op.sem_flg = 0; //aucune importance
	if((semop(semid, &op, 1)==-1)){
		perror("semop V()");
	}
	printf("fin thread %d\n",pthread_self());
	pthread_exit(NULL);
}
void raw(const char * event,int * sock,int semid,const char * ip_s,int port_s,pthread_mutex_t * socketAccess){
	char ip[TAILLE_IP];
	int port;
	char cmd[NAMESIZE];
	char rawcmd[NAMESIZE];
	sscanf(event,"%s %s : %d %s ",rawcmd,ip,&port,cmd);
	connect_program(ip,port,ip_s,port_s,sock,socketAccess);
	sock_puts(*sock, event);
}
void * f_thread_raw(int * args){
	printf("debut thread %d\n",pthread_self());
	//retarder l'execution du thread pour que la priorite soit effective
	sleep(2);
	int semid= args[1];
	char recived[BUFSIZ];
	memset((char *) &recived, 0, sizeof(recived));
	int ret;
	if((ret=recv(args[0], recived, sizeof(recived), 0))==-1)
		perror("receive");
	if(ret!=0){
		printf("%s",recived);
	}
	/*Liberation d'un thread client*/
	struct sembuf op;
	op.sem_num = 0; //Test si le thread est dispo
	op.sem_op = 1; //V()
	op.sem_flg = 0; //aucune importance
	if((semop(semid, &op, 1)==-1)){
		perror("semop V()");
	}
	printf("fin thread %d\n",pthread_self());
	pthread_exit(NULL);
	
	
}
void traffic(int * sock,const char * message,int semid){
	if(*sock!=-1){
		sock_puts(*sock, message);
	}
	else {
		printf("No connection done !\n");
	}
	
}

void list(int * sock,const char * message,int semid,filelist_t * listeFichiers,pthread_mutex_t *fileTableAccess){
	if(*sock!=-1){
		sock_puts(*sock, message);
	}
	else {
		printf("No connection done !\n");
	}
	

}
void neighbourhood(int * sock,const char * message,int semid){
	if(*sock!=-1){
		sock_puts(*sock, message);

	}
	else {
		printf("No connection done !\n");
	}
	
}
void * f_thread_get(tget * args){
	printf("debut thread %d\n",pthread_self());
	sleep(2);
	sleep(args->delay);
	int semid= args->semid;
	/*traitement*/
	char ready[NAMESIZE];
	char recived[BUFSIZ];
	memset((char *) &ready, 0, sizeof(ready));
	memset((char *) &recived, 0, sizeof(recived));
	int ret;
	download *down = args->down;

	int csocket;
	//ssize_t ret;
	int csock;
	SOCKADDR_IN sin;
	bzero((char*)&sin, sizeof(SOCKADDR_IN));
	char buffer[NAMESIZE] = "";
	/*creation de la socket*/
	csocket = socket(AF_INET, SOCK_STREAM, 0);
	/* Configuration de la connexion */
	sin.sin_addr.s_addr = inet_addr(down->ip);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(down->port);
	/* essai de connection*/
	if((csock=connect(csocket, (SOCKADDR*)&sin, sizeof(sin))) != SOCKET_ERROR){
		printf("Connexion à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));

		if((ret=recv(csocket, buffer,NAMESIZE, 0))==-1)
			perror("receive");
	}
	else {
		printf("Connexion impossible à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
	}
	int nbbloack;
	if(atoi(buffer)){
		nbbloack = atoi(buffer);
	}
	else {
		printf("problem get\n");
	}
	down->size = nbbloack;
	pthread_mutex_lock(args->downloadTableAccess);
	insererDownload(args->listeDownload,down);
	pthread_mutex_unlock(args->downloadTableAccess);
	char recived2[BUFSIZ];
	int fdopen;
	if ((fdopen=open(fpath(down->key,args->path),O_WRONLY|O_CREAT,0777))==-1) {
		perror("open");
		exit(EXIT_FAILURE);
	}
	while (nbbloack>0) {
		if((ret=recv(csocket, recived2, sizeof(recived2), 0))==-1)
			perror("receive");
		else if (ret !=0) {
			nbbloack--;
			pthread_mutex_lock(args->downloadTableAccess);
			down->pourcentage++;
			modify_download(args->listeDownload,down,down->pourcentage);
			pthread_mutex_unlock(args->downloadTableAccess);
			if (pwrite(fdopen, recived2,BUFSIZ, args->begin)==-1) {
				perror("pwrite");
				exit(EXIT_FAILURE);
			}
			sleep(1);

		}
	}
	close(csocket);
	pthread_mutex_lock(args->downloadTableAccess);
	supprimerDownload(args->listeDownload,*down);
	pthread_mutex_unlock(args->downloadTableAccess);


	/*Liberation d'un thread client*/
	struct sembuf op;
	op.sem_num = 0; //Test si le thread est dispo
	op.sem_op = 1; //V()
	op.sem_flg = 0; //aucune importance
	if((semop(semid, &op, 1)==-1)){
		perror("semop V()");
	}
	printf("fin thread %d\n",pthread_self());
	pthread_exit(NULL);
	
	
}
void get(int * sock,int semid,char *path,const char * message,ListeDownload * listeDownload,pthread_mutex_t * downloadTableAccess){
	if(*sock!=-1){
		sock_puts(*sock, message);
		
	}
	else {
		printf("No connection done !\n");
	}
	
}

int connect_program(const char * ip,int port,const char * ip_s,int port_s,int * sock,pthread_mutex_t * socketAccess ){
	pthread_mutex_lock(socketAccess);
	if(*sock!=-1){
		close(*sock);
	}
	//ssize_t ret;
	int csock;
	SOCKADDR_IN sin;
	bzero((char*)&sin, sizeof(SOCKADDR_IN));
	//char buffer[BUFSIZ] = "";
	/*creation de la socket*/
	*sock = socket(AF_INET,SOCK_STREAM,0);
	/* Configuration de la connexion */
	sin.sin_addr.s_addr = inet_addr(ip);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(port);
	/* essai de connection*/
	if((csock=connect(*sock, (SOCKADDR*)&sin, sizeof(sin))) != SOCKET_ERROR){
		printf("Connexion à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
		char  buffer[BUFSIZ];
		sprintf(buffer,"%s : %d",ip_s,port_s);
		sock_puts(*sock, buffer);
		
	}
	else {
		printf("Connexion impossible à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
	}
	pthread_mutex_unlock(socketAccess);
	return 0;
}
void help(){
	printf("\nCommandes disponibles :\n\n");

	couleur(34);
	gras(1);
	printf("   set : ");
	gras(0);
	couleur(0);
	printf("fournit la liste des options disponibles dans le programme\n");

	couleur(34);
	gras(1);
	printf("   set ");
	gras(0);
	couleur(34);
	printf("option=valeur : ");
	couleur(0);
	printf("modifie la valeur d'une option\n");

	couleur(34);
	gras(1);
	printf("   list");
	gras(0);
	couleur(34);
	printf("[options]");
	couleur(0);
	printf("donne la liste des ressources disponibles sur le reseau\n");

	couleur(34);
	gras(1);
	printf("   get ");
	gras(0);
	couleur(34);
	printf("cle : ");
	couleur(0);
	printf("recupere la ressource ");
	couleur(34);
	printf("cle\n");

	gras(1);
	printf("   info : ");
	gras(0);
	couleur(0);
	printf("affiche des informations, statistiques sur l'etat du programme\n");

	couleur(34);
	gras(1);
	printf("   download : ");
	gras(0);
	couleur(0);
	printf("affiche des informations sur les fichiers en cours de recuperation\n");

	couleur(34);
	gras(1);
	printf("   upload : ");
	gras(0);
	couleur(0);
	printf("affiche des information sur les fichiers en cours de transfert\n");

	couleur(34);
	gras(1);
	printf("   connect ");
	gras(0);
	couleur(34);
	printf("ip:port : ");
	couleur(0);
	printf("indique au programme de se connecter a un autre programme\n");

	couleur(34);
	gras(1);
	printf("   raw ");
	gras(0);
	couleur(34);
	printf("ip:port cmd : ");
	couleur(0);
	printf("envoie la commande de protocole ");
	couleur(34);
	printf("cmd ");
	couleur(0);
	printf("a un autre programme\n");

	couleur(34);
	gras(1);
	printf("   traffic : ");
	gras(0);
	couleur(0);
	printf("demande la liste des connexions en cours ou prevues\n");

	couleur(34);
	gras(1);
	printf("   neighbourhood : ");
	gras(0);
	couleur(0);
	printf("demande une liste de voisins communs\n");
	printf("\n");

	printf("Messages de l'application :\n\n");

	couleur(34);
	gras(1);
	printf("   file ");
	gras(0);
	couleur(34);
	printf("nom-de-fichier cle taille ip:port : ");
	couleur(0);
	printf("donne les informations sur un fichier\n");

	couleur(34);
	gras(1);
	printf("   ready ");
	gras(0);
	couleur(34);
	printf("cle delay ip port proto debut fin : ");
	couleur(0);
	printf("indique une transmission prevue dans ");
	couleur(34);
	printf("delay ");
	couleur(0);
	printf("secondes du segment ");
	couleur(34);
	printf("debut fin ");
	couleur(0);
	printf("du fichier identifie par ");
	couleur(34);
	printf("cle\n");

	couleur(34);
	gras(1);
	printf("   checksum ");
	gras(0);
	couleur(34);
	printf("cle taille-bloc debut fin checksum checksum... : ");
	couleur(0);
	printf("fournit la liste des des checksums pour une partie d'un fichier\n");

	couleur(34);
	gras(1);
	printf("   neighbour ");
	gras(0);
	couleur(34);
	printf("ip:port : ");
	couleur(0);
	printf("fournit l'adresse ip et le port tcp d'un des membres du reseau\n");

	couleur(34);
	gras(1);
	printf("   redirect ");
	gras(0);
	couleur(34);
	printf("cle ip:port : ");
	couleur(0);
	printf("message informatif indiquant a un client ou se trouve une ressource\n");

	couleur(34);
	gras(1);
	printf("   error ");
	gras(0);
	couleur(34);
	printf("requete[message] : ");
	couleur(0);
	printf("permet de signaler une erreur\n");

	printf("\n");
}
